home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 11
/
Cream of the Crop 11-1.iso
/
windows
/
boyer04.zip
/
BOYER.C
next >
Wrap
C/C++ Source or Header
|
1996-01-15
|
11KB
|
420 lines
/*-----------------------------------------------------------------------------
file: boyer.c
desc: Boyer-Moore text search algorithm (Windows version)
by: Patrick Ko
date: 6 Mar 91 - born
revi: 4 Apr 94 - port Windows 3.1
21 Aug 94 - support Windows DLL
13 Jan 95 v0.4 - bug fix FindIC() and FindBackwardIC()
note: use huge pointers to cater for big contiguous memory
-----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
Program Specification
in: search space s, pattern p
out: a pointer where p is exactly matched at s[i], NULL indicates fail
why: Boyer-Moore algorithm is best for general text search. On
"average" it takes length(s)/length(p) steps to match p in s.
ref: I recommend the following references:
"Algorithms". Robert Sedgewick. Addison Wesley Publishing Company.
1988. 2nd addition. p286. QA76.6.S435 1983
"Faster String Searches". Doctor Dobb's Journal. Volume 14
Issue 7 July 1989. Costas Menico. p74.
usage: e.g. to find a pattern "tiger" in a text in RAM starting at
pointer "txtp" with a length of 1,000,000 characters,
program like this:
LPSTR matchp;
SetFindPattern( "tiger" );
matchp = Find( txtp, 1000000L );
if (matchp != NULL)
// found
else
// not found
matchp = FindBackward( txtp + 1000000L - 1, 1000000L);
if (matchp != NULL)
// found
else
// not found
Q: Can I use Find() with a GlobalLock() pointer in Windows?
A: Yes.
Q: Must I delcare my pointer as HPSTR (huge pointer) ?
A: Not necessary. Find() and FindBackward() will convert your
LPSTR as HPSTR. However, in your own code you must aware
that you are holding a LPSTR and take care of the pointer
arithmetic and conversion. (see demo.c for example)
Q: What is the limit of the memory space I can search?
A: To the limit of huge pointer implementation and your hardware.
-----------------------------------------------------------------------------*/
#include <windows.h>
#include <ctype.h>
#include "boyer.h"
#ifdef BOYERDLL
UINT WINAPI WEP(int nParam)
{
nParam;
return 1;
}
int FAR PASCAL LibMain(
HANDLE hInstance, UINT wDataSeg, UINT cbHeapSize, LPSTR lpszCmdLine)
{
wDataSeg;
lpszCmdLine;
if (!cbHeapSize)
return 0;
UnlockData(0);
return 1;
}
#endif
/*-----------------------------------------------------------------------------
func: SetFindPattern
desc: initialize the pattern to be matched and generate skip table
pass: lpszPattern = pattern string
rtrn: HFIND - the find handle for further text search
-----------------------------------------------------------------------------*/
#ifdef BOYERDLL
HFIND FAR PASCAL SetFindPattern( LPSTR lpszPattern )
#else
HFIND SetFindPattern( LPSTR lpszPattern )
#endif
{
register unsigned int j;
register char c;
HFIND hfind;
LPFIND lpfind;
hfind = GlobalAlloc(GHND, sizeof(FINDSTRUCT));
if ((lpfind = (LPFIND)GlobalLock(hfind)) == NULL)
return NULL;
lpfind->plen = lstrlen( lpszPattern );
if (lpfind->plen > MAXPAT)
lpfind->plen = MAXPAT;
lstrcpy( (LPSTR)(lpfind->p), lpszPattern );
lstrcpy( (LPSTR)(lpfind->pIC), lpszPattern );
for (j=0; j<256; j++)
{
lpfind->skip[j] = lpfind->skipIC[j] = lpfind->plen;
lpfind->skipb[j] = lpfind->skipbIC[j] = lpfind->plen;
}
for (j=0; j<lpfind->plen; j++)
{
lpfind->pIC[j] = toupper(lpfind->pIC[j]);
c = lpszPattern[j];
lpfind->skip[c] = lpfind->skipIC[toupper(c)] = lpfind->plen - j - 1;
lpfind->skipb[c] = lpfind->skipbIC[toupper(c)] = j;
}
GlobalUnlock(hfind);
return (hfind);
}
/*-----------------------------------------------------------------------------
func: FreeFindPattern
desc: free the memory occupied by SetFindPattern
pass: hfind - the find handle
rtrn: nothing
-----------------------------------------------------------------------------*/
#ifdef BOYERDLL
void FAR PASCAL FreeFindPattern( HFIND hfind )
#else
void FreeFindPattern( HFIND hfind )
#endif
{
GlobalFree(hfind);
}
/*-----------------------------------------------------------------------------
func: Find
desc: match a pattern defined in SetFindPattern against string s
pass: hfind = the find handle created by SetFindPattern
s = start of search space, slen = length of s
rtrn: NULL = match fail
else = a LPSTR to p[0] in s matches p
-----------------------------------------------------------------------------*/
#ifdef BOYERDLL
LPSTR FAR PASCAL Find( HFIND hfind, LPSTR s, LONG slen )
#else
LPSTR Find( HFIND hfind, LPSTR s, LONG slen )
#endif
{
LONG i;
unsigned int n, j;
register char c;
LPFIND lpfind;
LPSTR lpresult;
HPSTR S;
if ((lpfind = (LPFIND)GlobalLock(hfind)) == NULL)
return (NULL);
i = j = lpfind->plen;
S = (HPSTR)s;
do
{
c = *(S + (i - 1));
if (c == lpfind->p[j - 1])
{
i--;
j--;
}
else
{
n = lpfind->plen - j + 1;
if (n > lpfind->skip[c] )
{
i += n;
}
else
{
i += lpfind->skip[c];
}
j = lpfind->plen;
}
}
while (j >= 1 && i <= slen);
/* match fails */
if (i >= slen)
{
lpresult = (LPSTR)NULL;
}
/* match successful */
else
{
lpresult = S + i;
}
GlobalUnlock(hfind);
return (lpresult);
}
/*-----------------------------------------------------------------------------
func: FindBackward
desc: match a pattern defined in SetFindPattern against string s
in backward manner
pass: hfind = the find handle created by SetFindPattern
s = start of search space, slen = length of s
rtrn: NULL = match fail
else = a LPSTR to p[0] in s matches p
-----------------------------------------------------------------------------*/
#ifdef BOYERDLL
LPSTR FAR PASCAL FindBackward( HFIND hfind, LPSTR s, LONG slen )
#else
LPSTR FindBackward( HFIND hfind, LPSTR s, LONG slen )
#endif
{
LONG i;
unsigned int n, j;
register char c;
LPFIND lpfind;
LPSTR lpresult;
HPSTR S;
if ((lpfind = (LPFIND)GlobalLock(hfind)) == NULL)
return (NULL);
i = j = lpfind->plen;
S = (HPSTR)s;
do
{
c = S[1 - i];
if (c == lpfind->p[lpfind->plen - j])
{
i--;
j--;
}
else
{
n = lpfind->plen - j + 1;
if (n > lpfind->skipb[c])
{
i += n;
}
else
{
i += lpfind->skipb[c];
}
j = lpfind->plen;
}
}
while (j >= 1 && i <= slen);
/* match fails */
if (i >= slen)
{
lpresult = (LPSTR)NULL;
}
/* match successful */
else
{
lpresult = (LPSTR)(S - i - lpfind->plen + 1);
}
GlobalUnlock(hfind);
return (lpresult);
}
/*-----------------------------------------------------------------------------
func: FindIC
desc: match a pattern defined in SetFindPattern against string s
and Ignore Case (i.e. case insensitive)
pass: hfind = the find handle created by SetFindPattern
s = start of search space, slen = length of s
rtrn: NULL = match fail
else = a LPSTR to p[0] in s matches p
-----------------------------------------------------------------------------*/
#ifdef BOYERDLL
LPSTR FAR PASCAL FindIC( HFIND hfind, LPSTR s, LONG slen )
#else
LPSTR FindIC( HFIND hfind, LPSTR s, LONG slen )
#endif
{
LONG i;
unsigned int n, j;
register char c;
LPFIND lpfind;
LPSTR lpresult;
HPSTR S;
if ((lpfind = (LPFIND)GlobalLock(hfind)) == NULL)
return (NULL);
i = j = lpfind->plen;
S = (HPSTR)s;
do
{
c = toupper(S[i - 1]);
if (c == lpfind->pIC[j - 1])
{
i--;
j--;
}
else
{
n = lpfind->plen - j + 1;
if (n > lpfind->skipIC[c])
{
i += n;
}
else
{
i += lpfind->skipIC[c];
}
j = lpfind->plen;
}
}
while (j >= 1 && i <= slen);
/* match fails */
if (i >= slen)
{
lpresult = (LPSTR)NULL;
}
/* match successful */
else
{
lpresult = S + i;
}
GlobalUnlock(hfind);
return (lpresult);
}
/*-----------------------------------------------------------------------------
func: FindBackwardIC
desc: match a pattern defined in SetFindPattern against string s
in backward manner and ignore case (i.e. case insensitive)
pass: hfind = the find handle created by SetFindPattern
s = start of search space, slen = length of s
rtrn: NULL = match fail
else = a LPSTR to p[0] in s matches p
-----------------------------------------------------------------------------*/
#ifdef BOYERDLL
LPSTR FAR PASCAL FindBackwardIC( HFIND hfind, LPSTR s, LONG slen )
#else
LPSTR FindBackwardIC( HFIND hfind, LPSTR s, LONG slen )
#endif
{
LONG i;
unsigned int n, j;
register char c;
LPFIND lpfind;
LPSTR lpresult;
HPSTR S;
if ((lpfind = (LPFIND)GlobalLock(hfind)) == NULL)
return (NULL);
i = j = lpfind->plen;
S = (HPSTR)s;
do
{
c = toupper(S[1 - i]);
if (c == lpfind->pIC[lpfind->plen - j])
{
i--;
j--;
}
else
{
n = lpfind->plen - j + 1;
if (n > lpfind->skipbIC[c] )
{
i += n;
}
else
{
i += lpfind->skipbIC[c];
}
j = lpfind->plen;
}
}
while (j >= 1 && i <= slen);
/* match fails */
if (i >= slen)
{
lpresult = (LPSTR)NULL;
}
/* match successful */
else
{
lpresult = (LPSTR)(S + 1 - i - lpfind->plen);
}
GlobalUnlock(hfind);
return (lpresult);
}